iT邦幫忙

2026 iThome 鐵人賽

DAY 6
0
自我挑戰組

賽博紓壓診所:從零打造純前端心理測驗與互動紓壓網頁系列 第 6

Day 06:使用者頭像與設定表單的資料狀態綁定

  • 分享至 

  • xImage
  •  

前言
在前幾天,我們陸續把「賽博紓壓診所」的排版、日夜模式、呼吸燈過場以及 SPA 單頁切換架構都搞定了!

但是大家不覺得,如果一進到首頁,每個人看到的畫面都長得一模一樣,好像少了一點「專屬感」嗎?既然這是一個幫大家解碼壓力的心理診所,我希望使用者在踏入診所的第一步,就能夠選擇自己今天的心情頭像(🐱、🐶、🦊、🐼、🦄 分別有這五種可以選擇),順便輸入 Email 來記錄長期分析。

今天我們就要來處理首頁的設定表單,用 JavaScript 把使用者的這些個人化選擇給抓下來並保存到變數裡,準備在後面的測驗結果中派上用場!

核心觀念:如何用 JS 捕捉使用者的選擇與輸入
在前端表單互動中,最常遇到的兩個需求就是:

  1. 點擊選擇: 使用者點了某個頭像時,我們要知道他選了哪一個,並幫被點到的頭像加上一個高亮的外框(selected class),同時把舊的拔掉。
  2. 文字輸入: 使用者在 Email 輸入框打字時,我們要隨時能透過 .value 把資料抓出來。
    只要掌握這兩個操作,我們就能把使用者的設定狀態完整搜集起來。

動手寫 Code(上):頭像網格與設定表單的樣式設定
首先,我們在網頁頭部樣式區域寫好頭像選擇器的 CSS。當使用者點擊某個頭像時,我們要讓它有放大跟框線高亮的互動回饋:

    [data-theme="dark"] {
        --bg-color: #121212;
        --card-bg: #1e1e1e;
        --primary-color: #64b5f6;
        --text-main: #e0e0e0;
        --text-muted: #9e9e9e;
    }

    body {
        font-family: 'Segoe UI', Microsoft JhengHei, sans-serif;
        background: var(--bg-color);
        color: var(--text-main);
        margin: 0;
        padding: 0;
        display: flex;
        justify-content: center;
        align-items: center;
        min-height: 100vh;
        transition: background 0.3s, color 0.3s;
    }

    .container {
        width: 100%;
        max-width: 600px;
        padding: 20px;
    }

    .card {
        background-color: var(--card-bg);
        border-radius: var(--border-radius);
        box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15);
        padding: 30px;
        text-align: center;
        transition: background-color 0.3s;
    }

    /* 設定表單區塊 */
    .config-section {
        background: var(--bg-color);
        padding: 15px;
        border-radius: 12px;
        margin-bottom: 20px;
        text-align: left;
        font-size: 0.85rem;
    }

    .config-section label {
        display: block;
        margin-bottom: 5px;
        font-weight: bold;
        color: var(--text-main);
    }

    .config-section input {
        width: 100%;
        padding: 8px;
        border-radius: 6px;
        border: 1px solid #ccc;
        margin-bottom: 12px;
        font-size: 0.9rem;
        background: var(--card-bg);
        color: var(--text-main);
        box-sizing: border-box;
    }

    /* 頭像網格排列 */
    .avatar-grid {
        display: flex;
        gap: 10px;
        justify-content: center;
        margin-bottom: 12px;
    }

    .avatar-option {
        font-size: 1.8rem;
        cursor: pointer;
        padding: 5px;
        border-radius: 50%;
        border: 2px solid transparent;
        transition: 0.2s;
    }

    .avatar-option.selected {
        border-color: var(--primary-color);
        background-color: var(--bg-color);
        transform: scale(1.1);
    }

    .btn {
        background-color: var(--primary-color);
        color: white;
        border: none;
        border-radius: 50px;
        padding: 12px 30px;
        font-size: 1rem;
        cursor: pointer;
        width: 100%;
        margin-top: 10px;
    }

    .hidden { display: none; }
</style>

動手寫 Code(下):首頁表單結構與資料綁定邏輯
接著在網頁主體中放入首頁的設定表單。我們透過寫好的 JavaScript 函式 selectAvatar 來切換選中狀態,並且在點擊「進入紓壓診所」時,把 Email 欄位的值抓出來存入變數:

<div class="container">
    
    <!-- 1. 首頁區塊(含頭像與 Email 設定) -->
    <div id="welcome-screen" class="card">
        <h1>🧠 賽博紓壓診所與解碼器</h1>
        <p>結合廟宇抽籤、能力雷達圖與惡搞病歷處方籤的頂級心靈小工具。</p>
        
        <div class="config-section">
            <label>選擇你的今日心情頭像:</label>
            <div class="avatar-grid" id="avatar-container">
                <div class="avatar-option selected" onclick="selectAvatar('🐱', this)">🐱</div>
                <div class="avatar-option" onclick="selectAvatar('🐶', this)">🐶</div>
                <div class="avatar-option" onclick="selectAvatar('🦊', this)">🦊</div>
                <div class="avatar-option" onclick="selectAvatar('🐼', this)">🐼</div>
                <div class="avatar-option" onclick="selectAvatar('🦄', this)">🦄</div>
            </div>

            <label for="user-email">📧 輸入 Email 記錄長期分析 (選填):</label>
            <input type="email" id="user-email" placeholder="example@email.com (不填則為單次紀錄)">
        </div>

        <button class="btn" onclick="goToBreathe()">進入紓壓診所</button>
    </div>

    <!-- 2. 呼吸過場畫面(預設隱藏) -->
    <div id="breathe-screen" class="card hidden">
        <h2>🧘 調整呼吸,放鬆心情</h2>
        <!-- 顯示玩家剛才選的頭像,確認有成功傳遞 -->
        <div id="user-avatar-display" style="font-size: 2.5rem; margin: 15px 0;">🐱</div>
        <p id="user-email-display" style="color: var(--text-muted);">尚未輸入 Email</p>
        <button class="btn" onclick="restartQuiz()">返回首頁</button>
    </div>

</div>

<script>
    // 宣告全域變數用來儲存使用者的設定狀態
    let selectedAvatarSymbol = '🐱';
    let userEmailValue = '';

    // 處理頭像選擇的邏輯
    function selectAvatar(symbol, element) {
        // 把所有頭像的 selected 樣式全部拔掉
        document.querySelectorAll('.avatar-option').forEach(el => {
            el.classList.remove('selected');
        });
        // 只幫被點擊的那個頭像加上 selected
        element.classList.add('selected');
        selectedAvatarSymbol = symbol;
        
        // 同步更新結果畫面的頭像顯示
        document.getElementById('user-avatar-display').innerText = symbol;
    }

    // 進入過場前,抓取 Email 輸入框的值並切換畫面
    function goToBreathe() {
        const emailInput = document.getElementById('user-email').value.trim();
        userEmailValue = emailInput;

        // 如果有輸入 Email 就顯示出來,沒輸入就顯示預設文字
        const emailDisplay = document.getElementById('user-email-display');
        if (userEmailValue) {
            emailDisplay.innerText = `已綁定帳號:${userEmailValue}`;
        } else {
            emailDisplay.innerText = "以單次訪客身分進行測驗";
        }

        // 切換畫面
        document.getElementById('welcome-screen').classList.add('hidden');
        document.getElementById('breathe-screen').classList.remove('hidden');
    }

    function restartQuiz() {
        document.getElementById('breathe-screen').classList.add('hidden');
        document.getElementById('welcome-screen').classList.remove('hidden');
    }
</script>

開發心得與架構省思
在處理這種多個選項的點擊切換時(像這次的頭像選擇),一開始常會忘記要先把同輩元素的樣式清掉,導致點到最後每個頭像都處於選中狀態。後來透過 querySelectorAll 搭配 forEach 先全部清空,再精準幫當前元素加上 selected,問題就迎刃而解了。

把使用者的輸入與選擇用變數保存下來,不僅能讓後續的畫面更有互動感,也為後面的診斷報告埋好了個人化的基礎。純前端的世界雖然沒有複雜的資料庫,但只要善用 JavaScript 的全域變數與 DOM 抓取,一樣能玩出很完整的互動體驗!

今日結語與明日預告
今天我們順利完成了首頁的心情頭像選擇與 Email 輸入綁定,讓使用者在進入測驗前就能留下個人化的設定。

明天 Day 07:第一階段總結:打造直覺流暢的溫馨首頁介面,我們要來回顧前六天所打下的基礎架構與互動視覺,為接下來重頭戲的心理測驗題目與計分邏輯做好萬全準備。我們明天見!


上一篇
Day 05:SPA 單頁式應用架構:用原生 JS 控制畫面狀態與流暢切換
下一篇
Day 07:第一階段總結:打造直覺流暢的溫馨首頁介面
系列文
賽博紓壓診所:從零打造純前端心理測驗與互動紓壓網頁7
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言